//
//  EAGLView.m
//  ARDetection
//
//  Created by NIMESH DESAI on 10/19/10.
//  Copyright __MyCompanyName__ 2010. All rights reserved.
//

#import "NSObject+Console.h"
#import "EAGLView.h"
#import "ES1Renderer.h"

@interface EAGLView ()

- (void) loadObject:(Object3D *)object;

@end


@implementation EAGLView

@synthesize	animating;
@dynamic	animationFrameInterval;
@synthesize markerID = _markerID;
@synthesize objectLoaded = _objectLoaded;

#pragma mark -
#pragma mark Custom getter/setter for Projection and ModelView

- (void)setModelViewMatrix:(NSArray *)matrix {
	[renderer setModelViewMatrix:matrix];	
	[self drawView];
}

- (void)setProjectionMatrix:(NSArray *)matrix {
	[renderer setProjectionMatrix:matrix];
	[renderer setupView:self.bounds.size.height height:self.bounds.size.width];
	[self drawView];
}

// You must implement this method
+ (Class)layerClass
{
    return [CAEAGLLayer class];
}

//The EAGL view is stored in the nib file. When it's unarchived it's sent -initWithCoder:
- (id)initWithCoder:(NSCoder*)coder
{    
    if ((self = [super initWithCoder:coder]))
    {
        // Get the layer
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;

        eaglLayer.opaque = FALSE;
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithBool:FALSE], 
										kEAGLDrawablePropertyRetainedBacking, 
										kEAGLColorFormatRGBA8, 
										kEAGLDrawablePropertyColorFormat, 
										nil];
		eaglLayer.contentsGravity = kCAGravityResizeAspectFill;
		eaglLayer.transform = CATransform3DRotate(CATransform3DIdentity,
												  M_PI/2.f,
												  0,
												  0,
												  1);
		eaglLayer.frame = self.bounds;

		renderer = [[ES1Renderer alloc] init];

		if (!renderer)
		{
			[self release];
			return nil;
		}

        animating = FALSE;
        displayLinkSupported = FALSE;
        animationFrameInterval = 1;
        displayLink = nil;
        animationTimer = nil;

        // A system version of 3.1 or greater is required to use CADisplayLink. The NSTimer
        // class is used as fallback when it isn't available.
        NSString *reqSysVer = @"3.1";
        NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
        if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
            displayLinkSupported = TRUE;
    }
	
	[self addConfigVariable:@"animationFrameInterval"
				  withValue:[NSNumber numberWithInteger:1]
				andCallback:@"updateAnimationInterval:"];
	
	self.markerID = -1;

    return self;
}

- (void) loadObject:(Object3D *)object
{
	[renderer loadObject:object];
	self.objectLoaded = TRUE;
}

- (void)drawView
{
    [renderer mainGameLoop];
}

- (void)layoutSubviews
{
    [renderer resizeFromLayer:(CAEAGLLayer*)self.layer];
}

- (void) startAnimating
{
	[renderer startAnimating];
}

- (void) stopAnimating
{
	[renderer stopAnimating];
}

- (NSInteger)animationFrameInterval
{
    return animationFrameInterval;
}

- (void)setAnimationFrameInterval:(NSInteger)frameInterval
{
    // Frame interval defines how many display frames must pass between each time the
    // display link fires. The display link will only fire 30 times a second when the
    // frame internal is two on a display that refreshes 60 times a second. The default
    // frame interval setting of one will fire 60 times a second when the display refreshes
    // at 60 times a second. A frame interval setting of less than one results in undefined
    // behavior.
    if (frameInterval >= 1)
    {
        animationFrameInterval = frameInterval;

        if (animating)
        {
            [self stopAnimation];
            [self startAnimation];
        }
    }
}

- (void)startAnimation
{
    if (!animating)
    {
        if (displayLinkSupported)
        {
            // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier 
			// versions will result in a warning, but can be dismissed if the system 
			// version runtime check for CADisplayLink exists in -initWithCoder:. The
			// runtime check ensures this code will not be called in system versions
			// earlier than 3.1.

            displayLink = [NSClassFromString(@"CADisplayLink") 
						   displayLinkWithTarget:self 
						   selector:@selector(drawView)];
            [displayLink setFrameInterval:animationFrameInterval];
            [displayLink addToRunLoop:[NSRunLoop currentRunLoop] 
							  forMode:NSDefaultRunLoopMode];
        }
        else
            animationTimer = [NSTimer scheduledTimerWithTimeInterval:(NSTimeInterval)((1.0 / 60.0) * animationFrameInterval) 
															  target:self 
															selector:@selector(drawView) 
															userInfo:nil 
															 repeats:TRUE];

        animating = TRUE;
    }
}

- (void)stopAnimation
{
    if (animating)
    {
        if (displayLinkSupported)
        {
            [displayLink invalidate];
            displayLink = nil;
        }
        else
        {
            [animationTimer invalidate];
            animationTimer = nil;
        }

        animating = FALSE;
    }
}

- (void)dealloc
{
    [renderer release];

    [super dealloc];
}

@end
